/**
 * @MessageEncoder.java  COPYRIGHT xiaojian
 * 
 * Created on 2017年7月12日 下午2:34:15
 */
package xj.toolkit.access;

import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import xiaojian.toolkit.bean.CommonsHeader;
import xiaojian.toolkit.util.ByteUtils;
import xj.toolkit.access.AccessHeader;
import xj.toolkit.access.AccessMsgCodeConstants;
import xj.toolkit.access.msg.AccessContentMessage;
import xj.toolkit.access.msg.AccessMessage;

/**
 * @author <a href="mailto:cxj2000@gmail.com">xiaojian.cao</a>
 *
 */
@ChannelHandler.Sharable
public class MessageEncoder extends MessageToByteEncoder<AccessMessage> {

	private static Logger logger = LoggerFactory.getLogger(MessageEncoder.class);
	
	@Override
	protected void encode(ChannelHandlerContext ctx, AccessMessage msg, ByteBuf out) throws Exception {
		logger.debug("encoding AccessMessage {} to wrappedBuffer", msg);
		
		
		final UUID id = msg.getIdentification();

		if (id == null) {
			logger.warn("{} is MutableIdentifyable but missing transactionId", msg);
			return;
		}

		// -- 组装头
		CommonsHeader header = msg.getCommonHeader();
		if (header == null) {
			logger.warn("{} is MutableIdentifyable but missing commonheader", msg);
			return;
		}

		// -- 组装access头。
		AccessHeader accessHeader = msg.getAccessHeader();
		if (accessHeader == null) {
			logger.warn("{} is MutableIdentifyable but missing accessheader", msg);
			return;
		}
		
		
		// --  得到内容，如果发现不是SYN消息，则有content。
		byte[] content = new byte[] {};
		if (header.getMessageCode() !=	AccessMsgCodeConstants.MSG_CODE_ACK) {
			AccessContentMessage acm = (AccessContentMessage)msg;
			content = acm.getContent();
		}

		if (logger.isDebugEnabled()) {
			logger.debug("content->{}, message id{}", ByteUtils.bytesAsHexString(content, 1024), id);
		}

		// -- 写入CommonsHeader。
		out.writeByte(header.getBasicVer());
		out.writeShort(header.getPayloadType());
		out.writeShort(header.getType());
		out.writeLong(header.getFirstTransaction());
		out.writeLong(header.getSecondTransaction());
		out.writeInt(header.getReserved());
		out.writeInt(header.getMessageCode());
		out.writeInt(content.length + AccessHeader.HEADER_LENGTH);

		// --写入AccessHeader
		out.writeShort(accessHeader.getSourceModuleId());
		out.writeShort(accessHeader.getSourceInstanceId());
		out.writeShort(accessHeader.getTargetModuleId());
		out.writeShort(accessHeader.getTargetInstanceId());
		out.writeInt(accessHeader.getReserved());

		out.writeBytes(content);
	}

}
